﻿
namespace __ts.Core.DBHelper
{
    using System;
    using System.Collections.Generic;
    using System.Data;
    using System.Data.SqlClient;
    using System.Reflection;

    /// <summary>
    /// Object To Model or IList<Model>
    /// </summary>
    public class DDRHelper
    {
        #region Object To Model
        /// <summary>
        /// Object To Model
        /// </summary>
        /// <typeparam name="T">T</typeparam>
        /// <param name="dr">SqlDataReader</param>
        /// <returns>T</returns>
        public static T ObjectToModel<T>(IDataReader dr)
        {
            try
            {
                //using (dr)
                //{
                    if (dr.Read())
                    {
                        Type modelType = typeof(T);
                        T model = Activator.CreateInstance<T>();
                        for (int i = 0; i < dr.FieldCount; i++)
                        {
                            PropertyInfo pi = modelType.GetProperty(dr.GetName(i));
                            if (pi != null)
                                pi.SetValue(model, HackType(dr[i], pi.PropertyType), null);
                        }
                        return model;
                    }
                //}
                return default(T);
            }
            catch (Exception ex)
            {
                throw ex;
            }
        }
        #endregion

        #region Object To IList<Model>
        /// <summary>
        /// Object To IList<Model>
        /// </summary>
        /// <typeparam name="T">T</typeparam>
        /// <param name="dr">SqlDataReader</param>
        /// <returns>IList<T></returns>
        public static IList<T> ObjectToList<T>(IDataReader dr)
        {
            //using (dr)
            //{
                IList<T> list = new List<T>();
                Type modelType = typeof(T);
                while (dr.Read())
                {
                    T model = Activator.CreateInstance<T>();
                    for (int i = 0; i < dr.FieldCount; i++)
                    {
                        PropertyInfo pi = modelType.GetProperty(dr.GetName(i));
                        if (pi != null)
                            pi.SetValue(model, HackType(dr[i], pi.PropertyType), null);
                    }
                    list.Add(model);
                }
                return list;
            //}
        }
        #endregion

        /*
        #region Object To Model
        /// <summary>
        /// Object To Model
        /// </summary>
        /// <typeparam name="T">T</typeparam>
        /// <param name="sqlConnectionString">SQL ConnectionString</param>
        /// <param name="proName">Procedure Name</param>
        /// <param name="param">SqlParameter[]</param>
        /// <returns>T</returns>
        public static T ObjectToModel<T>(string sqlConnectionString, string proName, SqlParameter[] param)
        {
            SqlDataReader dr = SqlHelper.ExecuteReader(sqlConnectionString, CommandType.StoredProcedure, proName, param);
            try
            {
                using (dr)
                {
                    if (dr.Read())
                    {
                        Type modelType = typeof(T);
                        T model = Activator.CreateInstance<T>();
                        for (int i = 0; i < dr.FieldCount; i++)
                        {
                            PropertyInfo pi = modelType.GetProperty(GetPropertyName(dr.GetName(i)));
                            if (pi != null)
                                pi.SetValue(model, HackType(dr[i], pi.PropertyType), null);
                        }
                        return model;
                    }
                }
                return default(T);
            }
            catch (Exception ex)
            {
                throw ex;
            }
        }
        #endregion

        #region Object To IList<Model>
        /// <summary>
        /// Object To IList
        /// </summary>
        /// <typeparam name="T">T</typeparam>
        /// <param name="sqlConnectionString">SQL ConnectionString</param>
        /// <param name="proName">Procedure Name</param>
        /// <param name="param">SqlParameter[]</param>
        /// <returns>IList<T></returns>
        public static IList<T> ObjectToList<T>(string sqlConnectionString, string proName, SqlParameter[] param)
        {
            SqlDataReader dr = SqlHelper.ExecuteReader(sqlConnectionString, CommandType.StoredProcedure, proName, param);
            using (dr)
            {
                IList<T> list = new List<T>();
                Type modelType = typeof(T);
                while (dr.Read())
                {
                    T model = Activator.CreateInstance<T>();
                    for (int i = 0; i < dr.FieldCount; i++)
                    {
                        PropertyInfo pi = modelType.GetProperty(GetPropertyName(dr.GetName(i)));
                        if (pi != null)
                            pi.SetValue(model, HackType(dr[i], pi.PropertyType), null);
                    }
                    list.Add(model);
                }
                return list;
            }
        }
        #endregion

        #region Object To Model
        /// <summary>
        /// Object To Model
        /// </summary>
        /// <typeparam name="T">T</typeparam>
        /// <param name="sqlConnectionString">SQL ConnectionString</param>
        /// <param name="cmdType">CommandType</param>
        /// <param name="cmdText">CommandText</param>
        /// <param name="param">SqlParameter[]</param>
        /// <returns>T</returns>
        public static T ObjectToModel<T>(string sqlConnectionString, CommandType cmdType, string cmdText, SqlParameter[] param)
        {
            SqlDataReader dr = SqlHelper.ExecuteReader(sqlConnectionString, cmdType, cmdText, param);
            try
            {
                using (dr)
                {
                    if (dr.Read())
                    {
                        Type modelType = typeof(T);
                        T model = Activator.CreateInstance<T>();
                        for (int i = 0; i < dr.FieldCount; i++)
                        {
                            PropertyInfo pi = modelType.GetProperty(GetPropertyName(dr.GetName(i)));
                            if (pi != null)
                                pi.SetValue(model, HackType(dr[i], pi.PropertyType), null);
                        }
                        return model;
                    }
                }
                return default(T);
            }
            catch (Exception ex)
            {
                throw ex;
            }
        }
        #endregion

        #region Object To IList<Model>
        /// <summary>
        /// Object To IList
        /// </summary>
        /// <typeparam name="T">T</typeparam>
        /// <param name="sqlConnectionString">SQL ConnectionString</param>
        /// <param name="cmdType">CommandType</param>
        /// <param name="cmdText">CommandText</param>
        /// <param name="param">SqlParameter[]</param>
        /// <returns>IList<T></returns>
        public static IList<T> ObjectToList<T>(string sqlConnectionString, CommandType cmdType, string cmdText, SqlParameter[] param)
        {
            SqlDataReader dr = SqlHelper.ExecuteReader(sqlConnectionString, cmdType, cmdText, param);
            using (dr)
            {
                IList<T> list = new List<T>();
                Type modelType = typeof(T);
                while (dr.Read())
                {
                    T model = Activator.CreateInstance<T>();
                    for (int i = 0; i < dr.FieldCount; i++)
                    {
                        PropertyInfo pi = modelType.GetProperty(GetPropertyName(dr.GetName(i)));
                        if (pi != null)
                            pi.SetValue(model, HackType(dr[i], pi.PropertyType), null);
                    }
                    list.Add(model);
                }
                return list;
            }
        }
        #endregion
        */
        #region 辅助类
        //数据类型进行判断转换
        private static object HackType(object value, Type conversionType)
        {
            if (Convert.IsDBNull(value))
                return null;

            if (conversionType.IsGenericType && conversionType.GetGenericTypeDefinition().Equals(typeof(Nullable<>)))
            {
                if (value == null)
                    return null;

                System.ComponentModel.NullableConverter nullableConverter = new System.ComponentModel.NullableConverter(conversionType);
                conversionType = nullableConverter.UnderlyingType;
            }
            return Convert.ChangeType(value, conversionType);
        }

        private static bool IsNullOrDBNull(object obj)
        {
            return ((obj is DBNull) || string.IsNullOrEmpty(obj.ToString())) ? true : false;
        }

        #endregion
    }
}
